{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c4d4deb6",
   "metadata": {},
   "source": [
    "# Controlled-Z 门脉冲校准\n",
    "\n",
    "*版权所有 (c) 2021 百度量子计算研究所，保留所有权利。*\n",
    "\n",
    "## 内容概要\n",
    "\n",
    "本教程介绍如何使用量脉（Quanlse）模拟真实实验中 Controlled-Z 门脉冲波形的校准。本教程的大纲如下：\n",
    "\n",
    "- 背景介绍\n",
    "- 准备工作\n",
    "- 初始化两量子比特模拟器\n",
    "- Controlled-Z 门脉冲标定\n",
    "    - 校准单量子比特门脉冲\n",
    "    - 校准 CZ 门的条件相位\n",
    "    - 抵消积累的动力学相位\n",
    "- 使用校准脉冲生成贝尔态"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d02c4a71",
   "metadata": {},
   "source": [
    "## 背景介绍\n",
    "\n",
    "在前面的标定教程中，我们介绍了单量子比特相关的参数标定方法。在本教程中，我们将介绍 Controlled-Z (CZ) 门的脉冲标定方法。在超导量子计算中，CZ 门是常用的两量子比特原生门，其基本原理是通过调节磁通控制量子比特频率，使得 $|11\\rangle$ 态和 $|20\\rangle$ ($|02\\rangle$) 态共振并发生回避交叉（avoided crossing），最终在 $|11\\rangle$ 态上积累 $\\pi$ 的相位，从而实现 CZ 门。CZ 门的作用可以理解为当控制量子比特处于 $|1\\rangle$ 态时，目标量子比特 $|1\\rangle$ 态的相位增加 $\\pi$，在两量子比特计算空间中的 CZ 门对应的矩阵表示为:\n",
    "\n",
    "$$\n",
    "U_{\\rm CZ} = |0\\rangle\\langle 0| \\otimes I + |1\\rangle\\langle1| \\otimes \\hat{\\sigma}^z = \\begin{bmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 1 & 0 & 0 \\\\ 0 & 0 & 1 & 0 \\\\ 0 & 0 & 0 & -1 \\end{bmatrix}. \n",
    "$$\n",
    "\n",
    "目前，量脉提供了 CZ 门的脉冲优化云服务，并在相应教程中介绍了相关原理，用户可点击 [Controlled-Z 门](https://quanlse.baidu.com/#/doc/tutorial-cz) 查看详细内容。在本教程中，我们将介绍 CZ 门在真实实验中的标定方法。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0918f19d",
   "metadata": {},
   "source": [
    "## 准备工作\n",
    "\n",
    "成功安装量脉后，您可以按照本教程运行下面的量脉程序。要运行此教程，您需要从量脉（Quanlse）和其它常用 Python 库导入以下包："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e0568aa4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import the dependent packages\n",
    "import numpy\n",
    "from math import pi\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# Import the two-qubit simulator\n",
    "from Quanlse.Superconduct.Simulator import pulseSim2Q\n",
    "\n",
    "# Import the basis function to generate state bector\n",
    "from Quanlse.Utils.Functions import basis\n",
    "\n",
    "# Import the center-aligned pulse scheduling strategy\n",
    "from Quanlse.Superconduct.SchedulerSupport.PipelineCenterAligned import centerAligned\n",
    "\n",
    "# Import the two qubit gate calibration functions\n",
    "from Quanlse.Superconduct.Calibration.TwoQubit import czCaliCondPhase, czCaliDynamicalPhase, \\\n",
    "    czCaliCondPhaseJob, czCaliDynamicalPhaseJob, caliSingleQubitGates\n",
    "\n",
    "# Import the operator for generating basis string list\n",
    "from Quanlse.Utils.Functions import computationalBasisList, project\n",
    "\n",
    "# Import the function for plot bar figures\n",
    "from Quanlse.Utils.Plot import plotBarGraph\n",
    "\n",
    "# Import the QOperation\n",
    "from Quanlse.QOperation.FixedGate import H, CZ"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9a67b2f5",
   "metadata": {},
   "source": [
    "## 初始化两量子比特模拟器\n",
    "\n",
    "首先，我们需要创建一个两量子比特模拟器来模拟 CZ 门的仿真。在量脉 2.1 中，我们新增了两量子比特模拟器模板，用户可以通过调用 `Quanlse.Simulator` 模块中的 `pulseSim2Q()` 函数创建一个实例化对象，其中参数 `dt` 表示求解薛定谔方程时的时间步长，而 `frameMode` 则表示采用何种参考坐标系进行仿真（`'lab'`、`'rot'` 分别表示实验室坐标系、旋转坐标系）："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f5581329",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Sampling period.\n",
    "dt = 0.01\n",
    "\n",
    "# The indexes of qubits for calibration\n",
    "q0 = 0\n",
    "q1 = 1\n",
    "\n",
    "# Instantiate the simulator object by a 3-qubit template.\n",
    "model = pulseSim2Q(dt=dt, frameMode='lab')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b695164c",
   "metadata": {},
   "source": [
    "该模拟器对两个直接耦合的三能级子系统进行建模，并预先定义了量子比特频率、失谐性强度以及比特间的耦合强度等属性；这些信息存储在模拟器的实例化对象 `model` 中，用户可以通过以下方式查看："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f3077a79",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"Qubit frequency (GHz):\\n    \", model.qubitFreq)\n",
    "print(\"Microwave drive frequency (GHz):\\n    \", model.driveFreq)\n",
    "print(\"Qubit anharmonicity (GHz):\\n    \", model.qubitAnharm)\n",
    "print(\"Qubit coupling map (GHz):\\n    \", model.couplingMap)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "972411bd",
   "metadata": {},
   "source": [
    "为了方便用户使用，`model` 中还内置了校准后的控制脉冲参数，用户可以通过 `model.conf` 属性查看："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a7174560",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"Microwave control pulse parameters (a.u.):\")\n",
    "print(f\"    q0: {model.conf['caliDataXY'][0]}\")\n",
    "print(f\"    q1: {model.conf['caliDataXY'][1]}\")\n",
    "print(\"Flux control pulse parameters (a.u.):\")\n",
    "print(f\"    q0: {model.conf['caliDataZ'][0]}\")\n",
    "print(f\"    q1: {model.conf['caliDataZ'][1]}\")\n",
    "print(\"CZ gate control pulse parameters (a.u.):\")\n",
    "print(f\"    q0q1: {model.conf['caliDataCZ'][(0, 1)]}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "305e873f",
   "metadata": {},
   "source": [
    "`pulseSim2Q()` 函数返回的是一个脉冲模拟器类型的对象 `Quanlse.Simulator.PulseModel`，它继承自 `Quanlse.Scheduler` 类型 ([点击查看 API](https://quanlse.baidu.com/api/Quanlse.Scheduler/Quanlse.Scheduler.html))，用户可自行设置脉冲排布策略。在这里我们使用居中对齐策略 `centerAligned`，并使用 `model.pipeline` 中的 `addPipelineJob()` 方法添加到 `model` 中，使得量脉调度器按照居中对齐的方式进行脉冲排布："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9dda999b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Set the center-aligned scheduling sctrategy\n",
    "model.pipeline.addPipelineJob(centerAligned)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7bf7ffb1",
   "metadata": {},
   "source": [
    "在这里，我们将需要 `model.savePulse` 设置为 `False` 以关闭脉冲缓存的选项，即禁止量脉调度器缓存每个量子门的脉冲："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d294351a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Prevent Quanlse Scheduler to cache the pulses\n",
    "model.savePulse = False"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aafde0c3",
   "metadata": {},
   "source": [
    "## Controlled-Z 门脉冲校准\n",
    "\n",
    "在完成了模拟环境的创建和配置后，我们开始进行 CZ 门的脉冲校准流程，主要包括如下几个步骤：\n",
    "\n",
    "   1. 校准单量子比特门脉冲\n",
    "   2. 校准 CZ 门的条件相位\n",
    "   3. 抵消积累的动力学相位"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8e445672",
   "metadata": {},
   "source": [
    "### 1. 校准单量子比特门脉冲\n",
    "\n",
    "由于在真实实验中超导量子比特不是理想的二能级系统，对于弱非谐性量子比特，能量泄漏到第三能级会使量子比特的状态脱离计算空间，因此我们需要考虑能级泄漏引入的误差。在 [DRAG 脉冲](https://quanlse.baidu.com/#/doc/tutorial-drag) 章节中，我们介绍了修正驱动脉冲的波形来消除能级泄露误差的原理和方法。在本教程中，我们也将使用 DRAG 脉冲来提升单量子比特门的保真度。\n",
    "\n",
    "在量脉 2.1 中，我们提供了两量子比特相关的校准模块 `Quanlse.Calibration.TwoQubit`，该模块中我们提供了两量子比特下 DRAG 脉冲的校准功能的功能，用户可以使用其中的 `caliSingleQubitGates()` 函数进行校准，并获得校准后脉冲的数据："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b4a33cd4",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# Obtain the amplitudes of Pi pulse and DRAG settings from the model configurations\n",
    "q0ParaInit = [model.conf[\"caliDataXY\"][q0][\"piAmp\"], model.conf[\"caliDataXY\"][q0][\"piAmp\"]]\n",
    "q1ParaInit = [model.conf[\"caliDataXY\"][q1][\"dragCoef\"], model.conf[\"caliDataXY\"][q1][\"dragCoef\"]]\n",
    "bounds = [(0, 1), (-1, 1), (0, 1), (-1, 1)]\n",
    "\n",
    "# Call the single-qubit calibration methods\n",
    "q0PiAmp, q0Drag, q1PiAmp, q1Drag, optGatesLoss = caliSingleQubitGates(\n",
    "    model, q0, q1, bounds=bounds, q0ParaInit=q0ParaInit, q1ParaInit=q1ParaInit)\n",
    "\n",
    "print(f\"The optimal pi amp of q0 and q1 is {round(q0PiAmp, 6)} and {round(q1PiAmp, 6)}\")\n",
    "print(f\"The optimal DRAG coefficient of q0 and q1 is {round(q0Drag, 6)} and {round(q1Drag, 6)}\")\n",
    "print(f\"The minimal infidelity is {round(optGatesLoss, 6)}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "612ec066",
   "metadata": {},
   "source": [
    "在完成脉冲数据的校准后，我们通过如下代码将校准好的 $\\pi$ 脉冲振幅以及 DRAG 修正系数添加到 `model.conf` 中："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b5cf9d86",
   "metadata": {},
   "outputs": [],
   "source": [
    "model.conf[\"caliDataXY\"][q0][\"piAmp\"] = q0PiAmp\n",
    "model.conf[\"caliDataXY\"][q0][\"dragCoef\"] = q0Drag\n",
    "model.conf[\"caliDataXY\"][q1][\"piAmp\"] = q1PiAmp\n",
    "model.conf[\"caliDataXY\"][q1][\"dragCoef\"] = q1Drag"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7d5e98b6",
   "metadata": {},
   "source": [
    "### 2. 校准 CZ 门的条件相位\n",
    "\n",
    "本小节中，我们将介绍如何校准条件相位 (conditional phase)，这也是实现 CZ 门最为核心的一步。我们可以通过改变磁通控制各能级的频率，从而使得各量子态 $|ij\\rangle$ 上累计不同的相位，对应的矩阵形式如下：\n",
    "\n",
    "$$\n",
    "{\\rm CZ}_{\\rm real} = \\begin{bmatrix}\n",
    "1 & 0 & 0 & 0 \\\\ \n",
    "0 & e^{i\\theta_{01}} & 0 & 0 \\\\ \n",
    "0 & 0 & e^{i\\theta_{10}} & 0 \\\\ \n",
    "0 & 0 & 0 & e^{i\\theta_{11}}\n",
    "\\end{bmatrix}.\n",
    "$$\n",
    "\n",
    "其中，$\\theta_{ij}$ 则表示量子态 $|ij\\rangle$ 获得的相位。要实现 CZ 门，我们首先需要实现条件相位为 $\\pi$，即使得 $\\theta_{11}=\\pi$，具体的方法为：我们在第一个量子比特 q0 上执行一个 $X/2$ 门，使其处于 $|0\\rangle$ 和 $|1\\rangle$ 的叠加态；同时，在第二个量子比特 q1 上执行一个 $X$ 门或 $I$ 门；随后，施加 $Z$ 控制以实现 $|11\\rangle$ 的相位积累；最后再在 q0 上执行一个 $X/2$ 门以改变坐标表象并显示其相位的改变，整体流程如下图所示：\n",
    "\n",
    "![fig:czCali_circuit](figures/cali-cz-circuit.png)\n",
    "\n",
    "其中 $\\alpha_0$ 和 $\\alpha_1$ 分别为第一个和第二个量子比特磁通脉冲的幅度。完成整个流程后对第一个量子比特 q0 测量，可以得到当 q0 分别为 $|0\\rangle$ 或 $|1\\rangle$ 态时的末态：\n",
    "\n",
    "$$\n",
    "\\left[R_x(\\pi/2)\\otimes I\\right] \\cdot |\\psi\\rangle_{\\rm q1=|0\\rangle} = \\frac{1-e^{i\\theta_{10}}}{2} |00\\rangle - \\frac{i\\left(1+e^{i\\theta_{10}}\\right)}{2} |10\\rangle, \\\\\n",
    "\\left[R_x(\\pi/2)\\otimes I\\right] \\cdot |\\psi\\rangle_{\\rm q1=|1\\rangle} = \\frac{e^{i\\theta_{01}}-e^{i\\theta_{11}}}{2} |01\\rangle - \\frac{i\\left(e^{i\\theta_{01}}+e^{i\\theta_{11}}\\right)}{2} |11\\rangle.\n",
    "$$\n",
    "\n",
    "我们可以发现，当 q1 上施加 $I$ 门时，若 $\\theta_{10}=0$，则末态为 $-i|10\\rangle$，因此对量子比特 q0 测量应该得到更多的 $|1\\rangle$ 态；而当 q1 上施加 $X$ 门时，若 $\\theta_{11}=\\pi$、$\\theta_{01}=0$，$R_x(\\pi/2) \\cdot |\\psi\\rangle_{\\rm q1=|1\\rangle}=|01\\rangle$，即对量子比特 q0 测量应该得到更多的 $|0\\rangle$ 态。因此我们可以将量子比特 q0 的测量结果作为损失函数进行优化，从而得到需要的条件相位：\n",
    "\n",
    "$$\n",
    "{\\rm Loss} = {\\rm Prob_{q1=|0\\rangle}(|01\\rangle+|11\\rangle)} + {\\rm Prob_{q1=|1\\rangle}(|00\\rangle+|10\\rangle)}.\n",
    "$$\n",
    "\n",
    "在 `Quanlse.Calibration.TwoQubit` 模块中，我们同样提供了校准磁通脉冲的函数 `czCaliCondPhase()`，该函数中包含了排布校准任务所需脉冲序列、测量以及优化等功能，用户可以直接使用该函数获得校准后的数据："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4202e614",
   "metadata": {},
   "outputs": [],
   "source": [
    "optQ0ZAmp, optQ1ZAmp, optCZLen, optCondPhaseLoss = czCaliCondPhase(\n",
    "    sche=model, q0=q0, q1=q1, maxIter=50)\n",
    "\n",
    "print(f\"The optimal loss value is {optCondPhaseLoss}\")\n",
    "print(f\"The optimal amplitude of Z pulse on qubit {q0} is {optQ0ZAmp}\")\n",
    "print(f\"The optimal amplitude of Z pulse on qubit {q1} is {optQ1ZAmp}\")\n",
    "print(f\"The optimal amplitude of duration of Z pulses is {optCZLen} ns\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "42e7b554",
   "metadata": {},
   "source": [
    "随后，我们在 `model` 的配置信息中修改脉冲时长 `czLen` 以及第一个和二个量子比特的 Z 脉冲的振幅 `q0ZAmp`、`q1ZAmp`，以备后续使用："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "98da5191",
   "metadata": {},
   "outputs": [],
   "source": [
    "model.conf[\"caliDataCZ\"][(0, 1)][\"q0ZAmp\"] = optQ0ZAmp\n",
    "model.conf[\"caliDataCZ\"][(0, 1)][\"q1ZAmp\"] = optQ1ZAmp\n",
    "model.conf[\"caliDataCZ\"][(0, 1)][\"czLen\"] = optCZLen"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "12905c5c",
   "metadata": {},
   "source": [
    "经过优化后，用于校准的脉冲为："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "17b291df",
   "metadata": {},
   "outputs": [],
   "source": [
    "condPhaseJobList = czCaliCondPhaseJob(model, q0, q1, optQ0ZAmp, optQ1ZAmp, optCZLen)\n",
    "print(r\"When the second qubit is initialized to |1>:\")\n",
    "condPhaseJobList.jobs[0].plot()\n",
    "print(r\"When the second qubit is initialized to |0>:\")\n",
    "condPhaseJobList.jobs[1].plot()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ea303a6d",
   "metadata": {},
   "source": [
    "### 3. 抵消积累的动力学相位\n",
    "\n",
    "在上面的步骤中，我们使用 $Z$ 通道上的脉冲来产生 $\\pi$ 的条件相位，但同时所施加磁通控制还会在两个量子比特上产生动力学相位的积累，因此我们需要设计脉冲进行抵消。\n",
    "\n",
    "在这里，我们使用 Virtual-Z (VZ) 门实现上述操作。VZ 门的基本原理是通过调整任意波发生器 (arbitrary wave generator, AWG) 的相位来实现与 $Z$ 方向上的旋转类似的操作。例如，我们希望进行两个 $X_{\\theta}$ 操作，但第二个 $X$ 操作在第一个 $X$ 操作的基础上有一个 $\\phi_0$ 的相位，即：\n",
    "\n",
    "$$\n",
    "X^{(\\phi_0)}_{\\theta} X_{\\theta} = e^{-i\\theta(\\hat{\\sigma}_x\\cos\\phi_0+\\hat{\\sigma}_y\\sin\\phi_0) / 2} X_{\\theta} = Z_{-\\phi_0}X_{\\theta}Z_{\\phi_0}X_{\\theta}.\n",
    "$$\n",
    "\n",
    "由于超导系统中对量子比特的测量是在 $Z$ 方向上进行的，这使得最后的 $Z_{-\\phi_0}$ 不会对观测值产生影响，因此可见调整 AWG 相位的效果与在两个 $X$ 门之间增加一个 $Z$ 门是等效的，即调节 AWG 的相位可视为添加了一个虚拟的 $Z$ 门。\n",
    "\n",
    "在本教程中，我们采用如下电路实现脉冲的校准：\n",
    "\n",
    "![fig:czCali_dynamical_phase_circuit](figures/cali-cz-dynamics-phase.png)\n",
    "\n",
    "这里，我们根据上述量子电路使用 Quanlse Scheduler 制备所需的脉冲序列，并使用 VZ 门实现 $Z_{\\theta_1}$ 和 $Z_{\\theta_2}$。随后，我们计算上述脉冲在模拟器中的模拟演化结果，并将末态与理想贝尔态 $(|00\\rangle + |11\\rangle) / \\sqrt{2}$ 之间的失真度作为损失函数进行优化。同样，用户可直接调用 `Quanlse.Calibration.TwoQubit` 模块中的 `czCaliDynamicalPhase()` 函数，该函数将输出最终优化后的 $\\theta_1^*$ 和 $\\theta_2^*$ 以及与理想贝尔态的失真度："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "815d7437",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "optQ0VZPhase, optQ1VZPhase, optDynaPhaseLoss = czCaliDynamicalPhase(\n",
    "    sche=model, q0=q0, q1=q1, method=\"Nelder-Mead\", q0VZPhaseInit=0., q1VZPhaseInit=0.)\n",
    "\n",
    "print(f\"The optimal loss value is {optDynaPhaseLoss}\")\n",
    "print(f\"The optimal phase correction on qubit {q0} is {optQ0VZPhase / 2 / pi} * 2pi\")\n",
    "print(f\"The optimal phase correction on qubit {q1} is {optQ1VZPhase / 2 / pi} * 2pi\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3967245e",
   "metadata": {},
   "source": [
    "值得注意的是，在上述步骤中，我们可以使用随即基准测试 (Randomized benckmarking) 或量子过程层析 (Quantum process tomography) 等技术代替上述第 3 步中计算贝尔态失真度的方法进行相位优化，以获得更准确的结果。\n",
    "\n",
    "最终，我们将校准好的相位信息存储到 `model` 中："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e8f193db",
   "metadata": {},
   "outputs": [],
   "source": [
    "model.conf[\"caliDataCZ\"][(0, 1)][\"q0VZPhase\"] = optQ0VZPhase\n",
    "model.conf[\"caliDataCZ\"][(0, 1)][\"q1VZPhase\"] = optQ1VZPhase"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "82f37c43",
   "metadata": {},
   "source": [
    "## 使用校准脉冲生成贝尔态\n",
    "\n",
    "通过前面的步骤，CZ 门所需的脉冲已经完成校准。接下来，我们可以使用已校准的脉冲波形编译给定的量子电路。用户可以直接通过 `model` 对象使用 **Quanlse Scheduler** 的所有功能。首先使用 `model.clearCircuit()` 方法清除当前模型中已定义的量子电路，随后添加制备贝尔态所需的量子电路，并调用 `model.schedule()` 方法编译生成所需的脉冲序列。在这里，编译过程将会调用前面保存的脉冲参数来生成各个量子门所需的脉冲，从而生成具有较高保真度的脉冲序列："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c67090a1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Clear the circuit\n",
    "model.clearCircuit()\n",
    "\n",
    "# Define the circuit\n",
    "H(model.Q[0])\n",
    "H(model.Q[1])\n",
    "CZ(model.Q[0], model.Q[1])\n",
    "H(model.Q[1])\n",
    "\n",
    "# Generate the ideal unitary of the quantum circuit\n",
    "uIdeal = model.getMatrix()\n",
    "\n",
    "# Generate the pulse for the circuit\n",
    "jobBell = model.schedule()\n",
    "jobBell.plot()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "98134c22",
   "metadata": {},
   "source": [
    "随后我们可以使用 `model.simulate()` 方法并传入脉冲任务 `jobBell`、初态 `state0` 以及重复次数 `shot` 来进行模拟演化，得到末态中各基态的计数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "afabfea9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Calculate final state\n",
    "finalState = model.simulate(\n",
    "    job=jobBell, state0=basis(model.sysLevel ** model.subSysNum, 0), shot=1000)\n",
    "\n",
    "# Print the population distance of Bell State\n",
    "pop = project(numpy.square(abs(finalState[0][\"state\"])).T[0], model.subSysNum, model.sysLevel, 2)\n",
    "stateIdeal = uIdeal @ basis(uIdeal.shape[0], 0).T[0]\n",
    "popIdeal = numpy.square(abs(stateIdeal))\n",
    "print(\"Distance of real and ideal Bell states:\", numpy.sum(numpy.abs(pop - popIdeal)) / len(pop))\n",
    "\n",
    "# Plot the population of computational basis\n",
    "plotBarGraph(computationalBasisList(2, 3), finalState[0][\"population\"], \n",
    "             \"Counts of the computational basis\", \"Computational Basis\", \"Counts\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c8315352",
   "metadata": {},
   "source": [
    "可见，使用上述的校准方法，我们实现了具有较高保真度的贝尔态。在真实的量子计算机中，我们可以使用量子过程层析（quantum process tomography）或随即基准测试（randomized benchmarking）进一步提升 CZ 门的保真度。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6f311af0",
   "metadata": {},
   "source": [
    "## 总结\n",
    "\n",
    "本教程旨在介绍使用量脉校准 CZ 门的方法。在阅读此教程后，用户可以通过这个链接 [tutorial-calibration-cz-cn.ipynb](https://github.com/baidu/Quanlse/blob/main/Tutorial/CN/tutorial-calibration-cz-cn.ipynb) 跳转到此 Jupyter Notebook 文档对应的 GitHub 页面获取相关的代码，尝试不同于本教程示例给出的参数值或函数以获得更深的理解。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2c0a86fa",
   "metadata": {},
   "source": [
    "## 参考文献\n",
    "\n",
    "\\[1\\] [Krantz, Philip, et al. \"A quantum engineer's guide to superconducting qubits.\" *Applied Physics Reviews* 6.2 (2019): 021318.](https://aip.scitation.org/doi/abs/10.1063/1.5089550)\n",
    "\n",
    "\\[2\\] [Yuan, Xu, et al. \"High-Fidelity, High-Scalability Two-Qubit Gate Scheme for Superconducting Qubits.\" *Physical Review Letters* 125 (2020): 240503 .](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.125.240503)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
